<template>
  <div class="comp">
    <div class="sub-title">平台类目属性</div>

    <div class="sub-form">
      <el-form ref="catePropertyForm" 
        :model="catePropertyForm" 
        :rules="formRules"
        label-position="right" 
        label-suffix="："
        :label-width="formLabelWidth" 
      >

        <div v-for="(item, index) in catePropertyForm.goodsPropertyList" :key="index">

          <template v-if="item.showFlag">

            <el-form-item :label="item.propName" :prop="item.prop">

              <!-- 文本 -->
              <template v-if="item.propInputType == 'text'">
                <el-input :ref="item.propId" v-model="item.propValue" class="width-350">

                  <!-- 后置内容 -->
                  <template v-if="item.textRule && item.textRule.appendRule" slot="append">
                    <template v-if="item.textRule.appendRule.appendInputType == 0">
                      <span>{{ item.textRule.appendRule.fixValue }}</span>
                    </template>

                    <template v-else-if="item.textRule.appendRule.appendInputType == 2">
                      <el-select v-model="item.additionalPropValueAndId" clearable filterable class="width-120">
                        <el-option v-for="(option, option_index) in item.textRule.appendRule.optionList" 
                          :key="option_index" 
                          :label="option.propValue" 
                          :value="option.propValueId ? (option.propValueId + '@#' + option.propValue) : option.propValue">
                        </el-option>
                      </el-select>
                    </template>

                  </template>
                </el-input>
              </template>

              <!-- 数字 -->
              <template v-else-if="item.propInputType == 'number'">
                <el-input :ref="item.propId" v-model="item.propValues[0]" class="width-350">

                  <!-- 后置内容 -->
                  <template v-if="item.numberRule && item.numberRule.appendRule" slot="append">
                    <template v-if="item.numberRule.appendRule.appendInputType == 0">
                      <span>{{ item.numberRule.appendRule.fixValue }}</span>
                    </template>

                    <template v-else-if="item.numberRule.appendRule.appendInputType == 2">
                      <el-select v-model="item.additionalPropValueAndId" clearable filterable class="width-120">
                        <el-option v-for="(option, option_index) in item.numberRule.appendRule.optionList" 
                          :key="option_index" 
                          :label="option.propValue" 
                          :value="option.propValueId ? (option.propValueId + '@#' + option.propValue) : option.propValue">
                        </el-option>
                      </el-select>
                    </template>

                  </template>
                </el-input>
              </template>

              <!-- 日期时间 -->
              <template v-else-if="item.propInputType == 'datetime'">
                <el-date-picker :ref="item.propId" 
                  v-model="item.propValue" 
                  value-format="timestamp"
                  :type="item.dateTimeRule.format === 'yearrange' ? 'monthrange' : item.dateTimeRule.format" 
                  :format="item.dateTimeRule.format === 'yearrange' ? 'yyyy' : ''"
                  class="width-350">
                </el-date-picker>
              </template>

              <!-- 图片 -->
              <template v-else-if="item.propInputType == 'image'">
                <div class="flex">
                  <template v-for="(image, index) in item.imageList">
                    <div class="pic-bar mar-r-30" :key="index">
                      <div @click="deleteImgages(item, index)">
                        <svg-icon icon-class="close" class="close-icon font-16 noraml-hide active"/>
                      </div>
                      <img class="picture" :src="image + '?imageView2/1/w/200/h/200/q/100'"/>
                    </div>
                  </template>

                  <el-upload list-type="picture-card" 
                    action="/api/common/uploadFiles" 
                    name="files" 
                    v-loading="item.fileLoading" 
                    v-if="item.imageList.length < item.imageRule.maxCount"
                    :data="token" 
                    :limit="item.imageRule.maxCount"
                    :multiple="item.imageRule.maxCount > 1 ? true : false"
                    :show-file-list="false" 
                    :before-upload="(file) => beforeUpload(file, item)" 
                    :on-exceed="(file, fileList) => handleExceed(file, fileList, item.imageRule.maxCount)" 
                    :on-success="(res, file, fileList) => handleUploadSuccess(res, file, fileList, item)"
                    >
                    <i class="el-icon-plus"></i>
                  </el-upload>
                </div>
                <div class="tips">
                  <span v-if="item.imageRule.maxCount > 1">最多可上传{{ item.imageRule.maxCount }}张&nbsp;</span>
                </div>
              </template>

              <!-- 单选 -->
              <template v-else-if="item.propInputType == 'select'">
                <el-select :ref="item.propId" 
                  v-model="item.propValueAndId" 
                  clearable 
                  filterable 
                  :allow-create="item.selectRule.customOptionFlag"
                  class="width-350" 
                  @change="doSelectChange(), doCascadeShow(item), doCascadeRequired(item)"
                >

                  <template v-for="(option, option_index) in item.selectRule.optionList">
                    <el-option v-if="!option.showParentValueIds || (option.showParentValueIds && option.optionShowFlag)"
                      :key="option_index" 
                      :label="option.propValue" 
                      :value="option.propValueId + '@#' + option.propValue">
                    </el-option>
                  </template>

                </el-select>
                <span class="font-red pad-l-10 font-12" v-if="item.cascadeHintFlag">下方有新的属性出现，请注意</span>

                <div class="tips">
                  <span v-if="item.selectRule.customOptionFlag">可自定义添加选项&nbsp;</span>
                </div>
              </template>

              <!-- 多选 -->
              <template v-else-if="item.propInputType == 'multiSelect'">
                <el-select :ref="item.propId" v-model="item.multiPropValueIds" 
                  multiple 
                  :multiple-limit="item.multiSelectRule.multipleMaxNum" 
                  clearable 
                  filterable 
                  :allow-create="item.multiSelectRule.customOptionFlag"
                  class="width-350">

                  <el-option v-for="(option, option_index) in item.multiSelectRule.optionList" 
                    :key="option_index" 
                    :label="option.propValue" 
                    :value="option.propValueId">
                  </el-option>
                </el-select>

                <div class="tips">
                  <span>最多可选择{{ item.multiSelectRule.multipleMaxNum }}项&nbsp;</span>
                  <span v-if="item.multiSelectRule.customOptionFlag">可自定义添加选项&nbsp;</span>
                </div>
              </template>

              <template v-else>
                <span>未知的组件类型</span>
              </template>

            </el-form-item>

          </template>

        </div>
      </el-form>
      
    </div>

  </div>
</template>

<script>
  import { getToken } from '@/utils/auth'

  export default {
    props: {
      // 属性列表
      propertyList: {
        type: Array
      },
      formLabelWidth: {
        type: String
      }
    },
    watch: {
      propertyList(newVal, oldVal) {
        if (newVal === oldVal) {
          return
        }
        this.init()
      }
    },
    data() {
      return {
        token: '',
        // 表单规则
        formRules: {},
        // 定时器
        timeoutHandle: '',
        // 类目属性表单
        catePropertyForm: {
          goodsPropertyList: []
        }
      }
    },
    created() {
      this.token = { accessToken: getToken() }
    },
    mounted() {
      this.init()
    },
    methods: {
      // 初始化
      init() {
        const originData = this.$options.data()
        this.catePropertyForm = originData.catePropertyForm
        this.formRules = originData.formRules
        this.$refs['catePropertyForm'].clearValidate()
        Object.assign(this.catePropertyForm.goodsPropertyList, this.propertyList)
        // console.log('dynamic init', this.catePropertyForm.goodsPropertyList)

        if (this.catePropertyForm.goodsPropertyList && this.catePropertyForm.goodsPropertyList.length > 0) {
          this.catePropertyForm.goodsPropertyList.forEach(e => {
            // 显示标识
            this.$set(e, 'showFlag', e.showRule.showRuleType === 1)
            // 文件loading
            this.$set(e, 'fileLoading', false)
            // 下拉组件绑定值
            this.$set(e, 'propValueAndId', '')
            // 多选组件绑定值
            this.$set(e, 'multiPropValueIds', [])
            // 附加属性绑定值
            this.$set(e, 'additionalPropValueAndId', '')
            // 图片组件绑定值
            this.$set(e, 'imageList', [])
            // 数字组件绑定值
            this.$set(e, 'propValues', [])
            // 其余组件绑定值
            this.$set(e, 'propValue', '')
          })
          // 按顺序执行 排序 -》 rule组装
          this.sortAssemble()
          this.ruleAssemble()
        }
      },
      // 排序组装（sortNo优先，propId次之，存在级联放于末尾，同组排序）
      sortAssemble() {
        const sortList = []
        const notConditionList = this.catePropertyForm.goodsPropertyList.filter(item => item.showRule.showRuleType !== 2)
        notConditionList.sort((a, b) => {
          const a_num = a.sortNo === 0 ? 0 : a.sortNo || a.propId
          const b_num = b.sortNo === 0 ? 0 : b.sortNo || b.propId
          return a_num - b_num
        })
        sortList.push(...notConditionList)

        // 构造同一组级联 内部排序
        const conditionMap = new Map()
        const conditionList = this.catePropertyForm.goodsPropertyList.filter(item => item.showRule.showRuleType === 2)
        conditionList.forEach(item => {
          let cascadeKey = ''
          // 条件排序
          item.showRule.showConditions.sort((a, b) => {
            return a.propId - b.propId
          })
          // 拼装key
          item.showRule.showConditions.forEach(cascade => {
            cascadeKey += cascade.propId + ':' + cascade.propValueIds.join(',') + ','
          })

          let itemList = conditionMap.get(cascadeKey)
          if (!itemList) {
            itemList = []
          }
          itemList.push(item)
          conditionMap.set(cascadeKey, itemList)
        })
        conditionMap.forEach((value, key, mapObj) => {
          sortList.push(...value)
        })
        this.catePropertyForm.goodsPropertyList = sortList
      },
      // 规则组装
      // 每个属性多个校验trigger要一致
      ruleAssemble() {
        const formRules = {}
        const triggerType = 'change'
        this.catePropertyForm.goodsPropertyList.forEach((item, index) => {
          // 组装prop   prop对应每个属性绑定的value对象
          let baseProp = 'goodsPropertyList.' + index + '.'
          switch (item.propInputType) {
            case 'select':
              baseProp += 'propValueAndId'
              break
            case 'multiSelect':
              baseProp += 'multiPropValueIds'
              break
            case 'image':
              baseProp += 'imageList'
              break
            case 'number':
              baseProp += 'propValues'
              break
            default:
              baseProp += 'propValue'
              break
          }
          this.$set(item, 'prop', baseProp)

          const itemRules = []
          const requiredFlag = item.requiredRule.requiredRuleType === 1
          itemRules.push({ required: requiredFlag, trigger: triggerType, message: item.propName + '不能为空' })
  
          switch (item.propInputType) {
            // 文本规则
            case 'text':
              var textRule = item.textRule
              if (textRule) {
                var textErrorMsg = textRule.errorHint
                // 正则校验
                if (textRule.regexps.length > 0) {
                  var textPattern = ''
                  textRule.regexps.forEach(regexp => {
                    textPattern += regexp
                  })
                  textPattern = '[' + textPattern + ']*'
                  itemRules.push({ pattern: new RegExp('^' + textPattern + '$'), trigger: triggerType, message: textErrorMsg || '请输入合法字符' })
                }
                // 长度校验
                var textLengthValidator = (rule, value, callback) => {
                  var length = item.propValue.length
                  if (length === 0) {
                    return callback()
                  }
                  var minLength = textRule.minLength
                  if (minLength > 0 && length < minLength) {
                    return callback(new Error(textErrorMsg || (item.propName + '输入的字符长度不能小于' + minLength)))
                  }
                  var maxLength = textRule.maxLength
                  if (maxLength > 0 && length > maxLength) {
                    return callback(new Error(textErrorMsg || (item.propName + '输入的字符长度不能大于' + maxLength)))
                  }
                  return callback()
                }
                itemRules.push({ trigger: triggerType, validator: textLengthValidator })

                // 后置内容
                if (textRule.appendRule) {
                  switch (textRule.appendRule.appendInputType) {
                    case 2:
                      var textAppendRuleValidator = (rule, value, callback) => {
                        // 主值有值则附加值也必须有
                        if (item[baseProp]) {
                          return item.additionalPropValueAndId ? callback() : callback(new Error('请选择附加属性'))
                        } else {
                          return callback()
                        }
                      }
                      itemRules.push({ trigger: triggerType, validator: textAppendRuleValidator })
                      break
                    default:
                      break
                  }
                }
              }
              break
            // 数字规则
            case 'number':
              var numberRule = item.numberRule
              // 数值大小校验
              var numberValueValidator = (rule, value, callback) => {
                var errorMsg
                item.propValues.forEach((n_v) => {
                  if (errorMsg) {
                    return
                  }
                  // 数字与精度校验
                  var numberPattern = '[\\d]*'
                  var numberErrorMsg = '请输入合法数字'
                  if (numberRule && numberRule.precision > 0) {
                    numberPattern = '([\\d]*|(0{1}))(\\.\\d{1,' + numberRule.precision + '})?'
                    numberErrorMsg += '，最多' + numberRule.precision + '位小数'
                  } else {
                    numberErrorMsg += '，不能有小数'
                  }
                  if (!new RegExp('^' + numberPattern + '$').test(n_v)) {
                    errorMsg = numberErrorMsg
                    return
                  }

                  // 最大值最小值校验
                  var numberValue = parseFloat(n_v)
                  if (isNaN(numberValue)) {
                    return
                  }
                  var minValue = parseFloat(numberRule.minValue)
                  if (typeof (minValue) === 'number') {
                    if (numberValue < minValue) {
                      errorMsg = '不能小于' + minValue
                      return
                    }
                  }
                  var maxValue = parseFloat(numberRule.maxValue)
                  if (typeof (maxValue) === 'number') {
                    if (numberValue > maxValue) {
                      errorMsg = '不能大于' + maxValue
                      return
                    }
                  }
                })
                return errorMsg ? callback(new Error(errorMsg)) : callback()
              }
              itemRules.push({ trigger: triggerType, validator: numberValueValidator })
  
              // 后置内容
              if (numberRule.appendRule) {
                switch (numberRule.appendRule.appendInputType) {
                  case 2:
                    var numberAppendRuleValidator = (rule, value, callback) => {
                      // 主值有值则附加值也必须有
                      if (item[baseProp][0]) {
                        return item.additionalPropValueAndId ? callback() : callback(new Error('请选择附加属性'))
                      } else {
                        return callback()
                      }
                    }
                    itemRules.push({ trigger: triggerType, validator: numberAppendRuleValidator })
                    break
                  default:
                    break
                }
              }
              break
            // 日期时间
            case 'datetime':
              var dateTimeRule = item.dateTimeRule
              var rangeValidator = (rule, value, callback) => {
                var minDateStr = dateTimeRule.minDateStr
                var maxDateStr = dateTimeRule.maxDateStr
                if (!(minDateStr || maxDateStr)) {
                  return callback()
                }
                var flag = true
                if (item.propValue) {
                  var minDateTime = minDateStr ? new Date(minDateStr).getTime() : ''
                  var maxDateTime = maxDateStr ? new Date(maxDateStr).getTime() : ''
                  if (Array.isArray(item.propValue)) {
                    // 范围
                    var startTime = item.propValue[0]
                    var endTime = item.propValue[1]

                    if (minDateTime && startTime) {
                      flag = (startTime >= minDateTime) && flag
                    }
                    if (maxDateTime && endTime) {
                      flag = (endTime <= maxDateTime) && flag
                    }
                  } else {
                    // 单值
                    var dateTimeVal = item.propValue
                    if (minDateTime) {
                      flag = (dateTimeVal >= minDateTime) && flag
                    }
                    if (maxDateTime) {
                      flag = (dateTimeVal <= maxDateTime) && flag
                    }
                  }
                }
                if (flag) {
                  return callback()
                } else {
                  var msg = item.propName + '必须在范围【' + (minDateStr || '不限') + ' - ' + (maxDateStr || '不限') + '】内'
                  return callback(new Error(msg))
                }
              }
              itemRules.push({ trigger: triggerType, validator: rangeValidator })
              break
            case 'select':
              break
            case 'multiSelect':
              break
            default:
              break
          }
          formRules[baseProp] = itemRules
        })
        this.formRules = formRules
        console.log('ruleAssemble after', formRules)
      },
      // 单选选择事件
      doSelectChange() {
        // not do 预留
      },
      // 级联下拉展示处理
      doCascadeShow(item) {
        const showConditionList = this.catePropertyForm.goodsPropertyList.filter(item => item.showRule.showRuleType === 2)
        if (showConditionList.length === 0) {
          return
        }
        const sourcePropId = item.propId
        const sourceValueId = item.propValueAndId ? item.propValueAndId.split('@#')[0] : ''
        // 本次打开的
        let showCount = 0
        // 本次隐藏的
        let hiddenCount = 0

        showConditionList.forEach(cateProperty => {
          const conditions = cateProperty.showRule.showConditions
          const existCascade = conditions.filter(cascadeRel => sourcePropId === cascadeRel.propId)
          // 未找到级联关系 跳过
          if (existCascade.length === 0) {
            return
          }
          let showFlag
          if (conditions.length === 1) {
            // 单层级联
            showFlag = sourceValueId ? conditions[0].propValueIds.includes(sourceValueId) : false
          } else {
            // 组合级联
            const subShowFlag = sourceValueId ? existCascade[0].propValueIds.includes(sourceValueId) : false
            existCascade[0].canShowFlag = subShowFlag

            // 是否全满足
            const canShowCount = conditions.filter(cascadeRel => cascadeRel.canShowFlag)
            showFlag = canShowCount === conditions.length
          }
          const originalShowFlag = cateProperty.showFlag
          cateProperty.showFlag = showFlag

          // 判断选项值是否存在级联显示
          if (cateProperty.propInputType === 'select') {
            const conditionOptions = cateProperty.selectRule.optionList.filter(op => op.showParentValueIds && op.showParentValueIds.length > 0)
            if (conditionOptions.length > 0) {
              conditionOptions.forEach(op => {
                const optionShowFlag = op.showParentValueIds.includes(sourceValueId)
                this.$set(op, 'optionShowFlag', optionShowFlag)
              })
              // 可能原本值已不存在 清空重选
              cateProperty.propValueAndId = ''
              // 多层级联case再次校验
              this.doCascadeShow(cateProperty)
            }
          }
          // 计数
          if (originalShowFlag && !showFlag) {
            hiddenCount++
          }
          if (!originalShowFlag && showFlag) {
            showCount++
          }
        })
        // 提示显示
        if ((showCount + hiddenCount) > 0) {
          if (showCount === 0) {
            this.$set(item, 'cascadeHintFlag', false)
            if (this.timeoutHandle) {
              clearTimeout(this.timeoutHandle)
            }
          } else {
            if (!item.cascadeHintFlag) {
              this.$set(item, 'cascadeHintFlag', true)
              this.timeoutHandle = setTimeout(() => {
                this.$set(item, 'cascadeHintFlag', false)
              }, 5000)
            }
          }
        }
      },
      // 级联下拉必填处理
      doCascadeRequired(item) {
        const requiredConditionList = this.catePropertyForm.goodsPropertyList.filter(item => item.requiredRule.requiredRuleType === 2)
        if (requiredConditionList.length === 0) {
          return
        }
        const sourcePropId = item.propId
        const sourceValueId = item.propValueAndId ? item.propValueAndId.split('@#')[0] : ''

        requiredConditionList.forEach(cateProperty => {
          const conditions = cateProperty.requiredRule.requiredConditions
          const existCascade = conditions.filter(cascadeRel => sourcePropId === cascadeRel.propId)
          // 未找到级联关系 跳过
          if (existCascade.length === 0) {
            return
          }
          let isRequired
          if (conditions.length === 1) {
            // 单层级联
            isRequired = sourceValueId ? conditions[0].propValueIds.includes(sourceValueId) : false
          } else {
            // 组合级联
            const subRequiredFlag = sourceValueId ? existCascade[0].propValueIds.includes(sourceValueId) : false
            existCascade[0].subRequiredFlag = subRequiredFlag

            // 是否全满足
            const canRequiredCount = conditions.filter(cascadeRel => cascadeRel.subRequiredFlag)
            isRequired = canRequiredCount === conditions.length
          }
          // 修改校验
          this.formRules[cateProperty.prop].forEach(rule => {
            var keys = Object.keys(rule)
            if (keys.includes('required')) {
              rule.required = isRequired
            }
          })
          this.$refs['catePropertyForm'].validateField(cateProperty.prop)
        })
      },
      // 超出事件
      handleExceed(file, fileList, maxCount) {
        this.$message({ type: 'warning', message: '最多可上传' + maxCount + '张' })
      },
      // 删除图片
      deleteImgages(item, index) {
        const goodsImages = item.imageList
        goodsImages.splice(index, 1)
        item.imageList = goodsImages
        this.$refs['catePropertyForm'].validateField(item.prop)
      },
      // 上传前事件
      beforeUpload(file, item) {
        const isJPG = file.type === 'image/jpeg'
        const isGIF = file.type === 'image/gif'
        const isPNG = file.type === 'image/png'
        const isBMP = file.type === 'image/bmp'
        if (!isJPG && !isGIF && !isPNG && !isBMP) {
          this.$message({ type: 'error', message: '上传图片必须是JPG/GIF/PNG/BMP 格式!' })
          return false
        }
        item.fileLoading = true
        return true
      },
      // 上传成功后事件
      handleUploadSuccess(res, file, fileList, item) {
        item.fileLoading = false
        if (res.code === 101) {
          item.imageList.push(res.data[0])
          this.$refs['catePropertyForm'].validateField(item.prop)
        } else {
          this.$message({ type: 'error', message: res.msg })
        }
      },
      // 表单校验 true：成功 false：失败
      checkForm() {
        let ret = true
        this.$refs['catePropertyForm'].validate((valid, result) => {
          if (!valid) {
            // const propKeys = Object.keys(result)
            // this.$refs['propertyForm'].fields.forEach(field => {
            //   const index = propKeys.indexOf(field.prop)
            //   if (index !== -1) {
            //     this.$emit('addVaildShow', field)
            //   }
            // })
            ret = false
          }
        })
        return ret
      },
      // 提交表单
      submitForm() {
        // // 过滤出显示的属性
        // const showList = this.catePropertyForm.goodsPropertyList.filter(item => item.showFlag)
        // const finalList = []
        // showList.forEach(item => {
        //   const obj = {
        //     propId: item.propId,
        //     propType: item.propType,
        //     propInputType: item.propInputType,
        //     sortNo: item.sortNo,
        //     propValue: item.propValue,
        //     propValueId: item.propValueId
        //   }
        // })
        console.log('goodsPropertyList', this.catePropertyForm.goodsPropertyList)
        return this.catePropertyForm.goodsPropertyList
      }
    }
  }
</script>

<style lang="less" scoped>
  .btn {
    padding: 15px 40px;
    margin: 30px 0 0 160px;
  }
  .el-date-editor.el-input {
    width: 350px !important;
  }
  .tips {
    color: gray;
    font-size: 12px;
    line-height: 1.2;
    padding-top: 5px;
  }
  .picture {
    width: 146px;
    height: 146px;
    display: block;
  }
  .pic-bar {
    position: relative;
    display: inline-block;
    .close-icon {
      position: absolute;
      right: -30px;
      top: -11px;
      width: 31px;
      height: 40px;
      padding: 0 7px;
      cursor: pointer;
    }
    span {
      position: absolute;
      right: 0;
      bottom: 0;
      width: 100%;
      display: block;
      color: #fff;
      text-align: center;
      padding: 3px 0;
      background: rgba(0, 0, 0, 0.5);
      cursor: pointer;
    }
  }
</style>